﻿using Logger4Net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace Hubberly
{
   public partial class MaskUpDown : UserControl
   {
      public class ChangedEventArgs : EventArgs
      {
         public decimal newValue;
      }
      public delegate void ChangedHandler(object sender, ChangedEventArgs eventArgs);
      public event ChangedHandler eventChanged;

      ////////////////////////////////////////////////////////////////////////
      //
      public MaskUpDown()
      {
         InitializeComponent();
         alert = false;
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public decimal currentValue
      {
         get
         {
            string asString = maskBox.Text.Trim();
            if (0 == asString.Length)
            {
               return -1;
            }
            value_ = decimal.Parse(string.Concat("0", asString));
            value_ = Math.Max(minimum_, Math.Min(maximum_, value_));
            return value_;
         }
         set
         {
            value_ = Math.Max(minimum_, Math.Min(maximum_, value));
            refresh();
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      private void refresh()
      {
         try
         {
            StringBuilder sb = new StringBuilder(value_.ToString("#,0"));
            sb[sb.Length - 1] = '~';
            string formatted = maskBuilder_.Replace("~", regex_.Replace(sb.ToString(), "9"));
            maskBox.Mask = formatted.Replace('~', '0');
            maskBox.Text = (0 <= value_) ? value_.ToString() : string.Empty;
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public bool readOnly
      {
         get { return maskBox.ReadOnly; }
         set
         {
            maskBox.ReadOnly = value;
            btnUp.Visible = btnDown.Visible = !value;
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public string maskBuilder
      {
         get { return maskBuilder_; }
         set
         {
            maskBuilder_ = value;
            refresh();
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public int delta
      {
         get { return delta_; }
         set { delta_ = value; }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public int maximum
      {
         get { return maximum_; }
         set { maximum_ = (0 < value) ? value : 0; }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public int minimum
      {
         get { return minimum_; }
         set { minimum_ = (0 < value) ? value : 0; }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public int shiftDelta
      {
         get { return shiftDelta_; }
         set { shiftDelta_ = value; }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public double output
      {
         get { return output_; }
         set { output_ = value; }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public bool alert
      {
         get { return alert_; }
         set
         {
            alert_ = value;
            maskBox.BackColor = alert_ ? SystemColors.ButtonHighlight : SystemColors.ButtonFace;
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      private void btnDown_Click(object sender, EventArgs e)
      {
         try
         {
            bool shifted = (Control.ModifierKeys == Keys.Shift);
            int delta = shifted ? shiftDelta_ : delta_;
            if (0 != (currentValue % delta))
            {
               currentValue = Math.Max(minimum_, currentValue - (currentValue % delta));
            }
            else
            {
               currentValue = Math.Max(minimum_, currentValue - delta);
            }
            checkFireChanged();
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      private void btnUp_Click(object sender, EventArgs e)
      {
         try
         {
            bool shifted = (Control.ModifierKeys == Keys.Shift);
            int delta = shifted ? shiftDelta_ : delta_;
            currentValue = currentValue + delta;
            currentValue -= currentValue % delta;
            currentValue = Math.Min(maximum_, currentValue);
            checkFireChanged();
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      private void maskBox_KeyPress(object sender, KeyPressEventArgs e)
      {
         try
         {
            if ('\r' == e.KeyChar)
            {
               e.Handled = true;
               checkFireChanged();
            }
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      private void maskBox_Leave(object sender, EventArgs e)
      {
         try
         {
            checkFireChanged();
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      private void checkFireChanged()
      {
         try
         {
            ChangedEventArgs eventArgs = new ChangedEventArgs();
            eventArgs.newValue = currentValue;
            if (null != eventChanged)
            {
               eventChanged(this, eventArgs);
            }
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
         }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      private static Logger logger_ = new Logger(typeof(MaskUpDown));
      private decimal value_;
      private int delta_ = 1;
      private int maximum_ = int.MaxValue;
      private int minimum_ = 0;
      private int shiftDelta_ = 10;
      private double output_ = 0.0;
      private bool alert_;
      private string maskBuilder_ = string.Empty;
      private static Regex regex_ = new Regex(@"\d");
   }
}
